package cn.wk.order.service.impl;

import cn.wk.basic.constant.ConstantPethome;
import cn.wk.basic.constant.PayConstant;
import cn.wk.basic.service.impl.BaseServiceImpl;
import cn.wk.basic.utils.CodeGenerateUtils;
import cn.wk.basic.utils.DistanceUtil;
import cn.wk.order.domain.OrderAddress;
import cn.wk.order.domain.ProductDetailOrder;
import cn.wk.order.domain.ProductOrder;
import cn.wk.order.domain.UserAddress;
import cn.wk.order.mapper.OrderAddressMapper;
import cn.wk.order.mapper.ProductDetailOrderMapper;
import cn.wk.order.mapper.ProductOrderMapper;
import cn.wk.order.mapper.UserAddressMapper;
import cn.wk.order.service.IProductOrderService;
import cn.wk.org.domain.Shop;
import cn.wk.org.mapper.ShopMapper;
import cn.wk.pay.domain.PayBill;
import cn.wk.pay.mapper.PayBillMapper;
import cn.wk.pay.service.IPayBillService;
import cn.wk.product.domain.Product;
import cn.wk.product.domain.ProductDetail;
import cn.wk.product.mapper.ProductMapper;
import cn.wk.quartz.domain.QuartzJobInfo;
import cn.wk.quartz.service.IQuartzService;
import cn.wk.quartz.util.QuartzUtils;
import cn.wk.user.domain.LoginInfo;
import cn.wk.user.domain.User;
import cn.wk.user.mapper.UserMapper;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

@Service
public class ProductOrderServiceImpl extends BaseServiceImpl<ProductOrder> implements IProductOrderService {
    @Autowired
    private UserAddressMapper userAddressMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private OrderAddressMapper orderAddressMapper;
    @Autowired
    private ShopMapper shopMapper;
    @Autowired
    private ProductOrderMapper productOrderMapper;
    @Autowired
    private ProductMapper productMapper;
    @Autowired
    private ProductDetailOrderMapper productDetailOrderMapper;
    @Autowired
    private PayBillMapper payBillMapper;
    @Autowired
    private IPayBillService payBillService;
    @Autowired
    private IQuartzService quartzService;
    /**
     * 保存服务订单
     * @param map
     * @param loginInfo
     */
    @Override
    @Transactional
    public String submitOrder(Map<String, Object> map, LoginInfo loginInfo) {
        //获取用户填写的地址id
        Long addressId = Long.parseLong(map.get("addressId").toString());
        //根据id获取用户地址订单对象
        UserAddress userAddress = userAddressMapper.findById(addressId);
        //根据登录信息获取user对象
        User user = userMapper.findByLogininfoId(loginInfo.getId());
        //创建订单地址的表
        OrderAddress orderAddress = createdOrderAddress(userAddress, user);
        //保存订单地址的表
        orderAddressMapper.save(orderAddress);
        //创建服务订单(pricer价格目前是空的)
        ProductOrder productOrder = createdOrderProduct(orderAddress,user);
        //保存服务订单
        productOrderMapper.save(productOrder);
        //拿出所有服务明细
        List<Map<String, Integer>> products = (List<Map<String, Integer>>) map.get("products");
        //创建服务明细
        List<ProductDetailOrder> productDetailOrders = createdProductDetail(products, productOrder);
        //保存服务明细
        productDetailOrderMapper.batchSave(productDetailOrders);
        //修改服务订单中的价格
        productOrderMapper.update(productOrder);
        //获取支付方式
        Integer payType = (Integer) map.get("payType");
        //创建支付单对象
        PayBill payBill = createdPayBill(productOrder,payType);
        payBillMapper.save(payBill);
        //添加定时任务
        QuartzJobInfo quartzJobInfo = createdQuartzJobInfo(productOrder);
        //执行定时任务
        quartzService.addJob(quartzJobInfo);
        //选择支付方式
        switch (payType){
            case 1://银联
                break;
            case 2://微信
                break;
            case 3://支付宝
                //跳转
                return payBillService.goBuy(productOrder);
        }
        return null;
    }

    /**
     * 创建定时任务
     * @return
     */
    private QuartzJobInfo createdQuartzJobInfo(ProductOrder productOrder) {
        QuartzJobInfo quartzJobInfo = new QuartzJobInfo();
        //设置type类型
        quartzJobInfo.setType(PayConstant.BUSINESSTYPE_PRODUCT);
        //设置个名字
        quartzJobInfo.setJobName(PayConstant.BUSINESSTYPE_PRODUCT+productOrder.getOrderSn());
        //设置时间
        quartzJobInfo.setFireDate(productOrder.getLastPayTime());
            Map<String, Object> map = new HashMap<>();
        //把ordersn传入
        map.put("orderSn", productOrder.getOrderSn());
        //传入参数
        quartzJobInfo.setParams(map);
        return quartzJobInfo;
    }

    /**
     * 创建支付单对象
     * @return
     */
    private PayBill createdPayBill(ProductOrder productOrder,Integer payType) {
        PayBill payBill = new PayBill();
        //摘要
        payBill.setDigest(productOrder.getDigest());
        //交易金额
        payBill.setMoney(productOrder.getPrice());
        //最后支付时间
        payBill.setLastPayTime(productOrder.getLastPayTime());
        //支付类型 1银联   2 微信  3支付宝
        payBill.setPayChannel(payType);
        //业务类型
        payBill.setBusinessType(PayConstant.BUSINESSTYPE_PRODUCT);
        //业务键
        payBill.setBusinessKey(productOrder.getId());
        //用户
        payBill.setUser(productOrder.getUser());
        //店铺
        payBill.setShop(productOrder.getShop());
        //昵称
        payBill.setNickName(productOrder.getUser().getUsername());
        //设置订单编号
        payBill.setOrderSn(productOrder.getOrderSn());
        return payBill;
    }

    /**
     * 创建服务明细
     * @param products
     * @param productOrder
     * @return
     */
    private List<ProductDetailOrder> createdProductDetail(List<Map<String, Integer>> products, ProductOrder productOrder) {
        //用一个集合来接收服务订单明细
        ArrayList<ProductDetailOrder> productDetailOrders = new ArrayList<>();
        //定义一个bigdecimal
        BigDecimal bigDecimal = new BigDecimal("0");
        //遍历传进来的集合
        for (Map<String, Integer> map : products){
            //创建服务明细对象
            ProductDetailOrder productDetailOrder = new ProductDetailOrder();
            //根据id去查询商品
            Long id = Long.parseLong(map.get("id").toString());
            Product product = productMapper.findById(id);
            //添加数量
            productDetailOrder.setSalecount(map.get("num"));
            //添加product
            productDetailOrder.setProduct(product);
            //添加服务订单
            productDetailOrder.setOrder(productOrder);
            //把服务明细装进集合中
            productDetailOrders.add(productDetailOrder);
            //计算价格
            bigDecimal = bigDecimal.add(product.getSaleprice().multiply(new BigDecimal(map.get("num").toString())));
        }
        //把总价格设置到服务订单中去
        productOrder.setPrice(bigDecimal);
        return productDetailOrders;
    }

    /**
     * 创建服务订单
     * @param orderAddress 通过其地址为其匹配最近的shop
     * @param user user_id
     * @return
     */
    private ProductOrder createdOrderProduct(OrderAddress orderAddress, User user) {
        //先获取所有店铺
        List<Shop> all = shopMapper.findAll();
        //获取最近的shop
        Shop shop = DistanceUtil.getNearestShop(DistanceUtil.getPoint(orderAddress.getAddress()), all);
        ProductOrder productOrder = new ProductOrder();
        //设置最近的shop
        productOrder.setShop(shop);
        //设置购买的用户
        productOrder.setUser(user);
        //摘要
        productOrder.setDigest("这里是"+shop.getName()+"提供的服务");
        //支付单号和订单地址编号一样
        productOrder.setOrderSn(orderAddress.getOrderSn());
        //最后支付时间
        productOrder.setLastPayTime(DateUtils.addSeconds(new Date(),15));
        return productOrder;

    }

    /**
     * 创建订单地址
     * @param userAddress
     * @param user
     */
    private OrderAddress createdOrderAddress(UserAddress userAddress, User user) {
        OrderAddress orderAddress = new OrderAddress();
        BeanUtils.copyProperties(userAddress,orderAddress);
        //重新设置创建时间
        orderAddress.setCreateTime(new Date());
        //根据用户id设置订单号
        orderAddress.setOrderSn(CodeGenerateUtils.generateOrderSn(user.getId()));
        return orderAddress;
    }
}
